{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# IQPE and evolution of VQE output state\n",
    "\n",
    "This notebook demonstrates using an output result state from [VQE](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.VQE.html) as the input, starting state for evolution by the [IQPE](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.IQPE.html) (Iterative Quantum Phase Estimation) algorithm. \n",
    "\n",
    "This is accomplished by first running VQE and then preparing IQPE's initial state using the variational form as produced by VQE upon its termination."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from qiskit import BasicAer\n",
    "from qiskit.aqua import aqua_globals, QuantumInstance\n",
    "from qiskit.aqua.algorithms import VQE, NumPyMinimumEigensolver, IQPE\n",
    "from qiskit.aqua.operators import I, X, Z\n",
    "from qiskit.circuit.library import TwoLocal\n",
    "from qiskit.aqua.components.optimizers import SPSA\n",
    "from qiskit.aqua.components.initial_states.var_form_based import VarFormBased"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First we create a qubit operator for VQE. Here we will use the same operator as used in the algorithms introduction, which was originally computed by Qiskit Chemistry for an H2 molecule."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "H2_op = (-1.052373245772859 * I ^ I) + \\\n",
    "        (0.39793742484318045 * I ^ Z) + \\\n",
    "        (-0.39793742484318045 * Z ^ I) + \\\n",
    "        (-0.01128010425623538 * Z ^ Z) + \\\n",
    "        (0.18093119978423156 * X ^ X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First we will use the classical NumPyMinimumEigensolver to compute a reference ground state energy value so later we can compare with the VQE result first, then IQPE's."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reference value: -1.85728\n"
     ]
    }
   ],
   "source": [
    "npme = NumPyMinimumEigensolver()\n",
    "result = npme.compute_minimum_eigenvalue(operator=H2_op)\n",
    "ref_value = result.eigenvalue.real\n",
    "print(f'Reference value: {ref_value:.5f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Having established the reference ground energy, we next carry on with our experiment. First we configure a VQE algorithm instance. The idea is that we can set an termination condition such that the VQE instance returns rather quickly with a rough estimation result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "VQE estimated the ground energy to be -1.74063\n",
      "Delta from reference energy value is 0.11664\n"
     ]
    }
   ],
   "source": [
    "seed = 5\n",
    "aqua_globals.random_seed = seed\n",
    "\n",
    "var_form = TwoLocal(rotation_blocks=['ry', 'rz'], entanglement_blocks='cz', reps=3)\n",
    "spsa = SPSA(maxiter=10)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "qi = QuantumInstance(backend, seed_simulator=seed, seed_transpiler=seed)\n",
    "\n",
    "vqe = VQE(var_form=var_form, optimizer=spsa, quantum_instance=qi)\n",
    "result_vqe = vqe.compute_minimum_eigenvalue(operator=H2_op)\n",
    "\n",
    "print(f'VQE estimated the ground energy to be {result_vqe.eigenvalue.real:.5f}')\n",
    "print(f'Delta from reference energy value is {(result_vqe.eigenvalue.real - ref_value):.5f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As previously indicated, the energy estimation result is rather rough--it is far from being an acceptable final estimation figure. But, it is close enough such that the accompanying variational form might be a reasonably good approximation to the ground eigenstate, which means the corresponding wave function can serve as the initial state for the IQPE execution that follows. We next prepare such an initial state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "vqe_state = VarFormBased(var_form, result_vqe.optimal_parameters)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the VQE-generated quantum state wave function prepared for the initial state, we now go ahead with configuring and running an IQPE instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Continuing with VQE's result, IQPE estimated the ground energy to be -1.84917\n",
      "Delta from reference energy value is 0.00811\n"
     ]
    }
   ],
   "source": [
    "qi = QuantumInstance(backend, shots=100, seed_simulator=seed, seed_transpiler=seed)\n",
    "\n",
    "iqpe = IQPE(state_in=vqe_state, num_time_slices=1, num_iterations=6,\n",
    "            expansion_mode='suzuki', expansion_order=2, quantum_instance=qi)\n",
    "result_iqpe = result_vqe = iqpe.compute_minimum_eigenvalue(operator=H2_op)\n",
    "\n",
    "print(f\"Continuing with VQE's result, IQPE estimated the ground energy to be {result_iqpe.eigenvalue.real:.5f}\")\n",
    "print(f'Delta from reference energy value is {(result_iqpe.eigenvalue.real - ref_value):.5f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As can be seen, the resultant ground state energy estimation, as produced by IQPE, is much more accurate that the intermediate result produced by VQE."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<h3>Version Information</h3><table><tr><th>Qiskit Software</th><th>Version</th></tr><tr><td>Qiskit</td><td>0.23.0</td></tr><tr><td>Terra</td><td>0.16.0</td></tr><tr><td>Aer</td><td>0.7.0</td></tr><tr><td>Ignis</td><td>0.5.0</td></tr><tr><td>Aqua</td><td>0.8.0</td></tr><tr><td>IBM Q Provider</td><td>0.11.0</td></tr><tr><th>System information</th></tr><tr><td>Python</td><td>3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:09:58) \n",
       "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]</td></tr><tr><td>OS</td><td>Linux</td></tr><tr><td>CPUs</td><td>1</td></tr><tr><td>Memory (Gb)</td><td>5.827335357666016</td></tr><tr><td colspan='2'>Sat Nov 07 16:15:38 2020 EST</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style='width: 100%; background-color:#d5d9e0;padding-left: 10px; padding-bottom: 10px; padding-right: 10px; padding-top: 5px'><h3>This code is a part of Qiskit</h3><p>&copy; Copyright IBM 2017, 2020.</p><p>This code is licensed under the Apache License, Version 2.0. You may<br>obtain a copy of this license in the LICENSE.txt file in the root directory<br> of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.<p>Any modifications or derivative works of this code must retain this<br>copyright notice, and modified files need to carry a notice indicating<br>that they have been altered from the originals.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import qiskit.tools.jupyter\n",
    "%qiskit_version_table\n",
    "%qiskit_copyright"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
